namespace TomatoBreak.DomainObjects
{
    using System;
    using System.Collections.Generic;
    using System.Dynamic;
    using System.Linq.Expressions;

    using Infrastructure;

    public abstract class Entity : IHasDynamicProperties, IEquatable<Entity>
    {
        private readonly IDictionary<string, object> dynamicProperties =
            new Dictionary<string, object>();

        public virtual Guid Id { get; protected set; }

        public virtual DynamicMetaObject GetMetaObject(Expression parameter)
        {
            return new DynamicPropertiesMetaObject(parameter, this);
        }

        public virtual object GetProperty(string name)
        {
            return dynamicProperties[name];
        }

        public virtual void SetProperty(string name, object value)
        {
            dynamicProperties[name] = value;
        }

        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }

        public virtual bool Equals(Entity other)
        {
            return !ReferenceEquals(null, other) &&
                   (ReferenceEquals(this, other) || other.Id.Equals(Id));
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }

            if (ReferenceEquals(this, obj))
            {
                return true;
            }

            return GetType() == obj.GetType() && Equals((Entity)obj);
        }
    }
}